package org.snp

import scala.reflect.BeanProperty
import java.util.regex.Pattern

class Voter extends Fields {
  @BeanProperty
  var id: String = null
  @BeanProperty
  var registerNum: String = null
  @BeanProperty
  var salutation: String = null
  @BeanProperty
  var firstName: String = null
  @BeanProperty
  var middleInitial: String = null
  @BeanProperty
  var lastName: String = null
  @BeanProperty
  var gender: String = null
  @BeanProperty
  var homePhone: String = null
  @BeanProperty
  var postal: String = null
  @BeanProperty
  var snpCategory: String = null
  @BeanProperty
  var aline1: String = null
  @BeanProperty
  var aline2: String = null
  @BeanProperty
  var village: String = null
  @BeanProperty
  var district: String = null
  @BeanProperty
  var city: String = null
  @BeanProperty
  var postcode: String = null
  @BeanProperty
  var leafletCode: String = null

  def flatNum(): Option[Int] = {
    if (aline1.toLowerCase().contains("ground")) {
      val numStr = aline1.replaceAll("[^\\d]", "")
      if (numStr.size > 0)
        return Some(Integer.parseInt(numStr))
    } else {
      Array("/", "-").foreach {
        sep =>
          val flatNum = flatNumForSep(sep)
          if (flatNum != None)
            return flatNum
      }
    }

    def flatNumForSep(sep: String): Option[Int] = {
      if (aline1.matches(".*\\d" + sep + "\\d.*")) {
        val numStrs = aline1.split(sep)
        val flatNum = numStrs(1).replaceAll("[^\\d]", "")
        if (flatNum.size > 0)
          return Some(Integer.parseInt(flatNum))
      }
      None
    }

    None
  }

  def floorNum(): Option[Int] = {
    if (aline1.toLowerCase().contains("ground")) {
      return Some(0)
    } else {
      Array("/", "-").foreach {
        sep =>
          val floorNum = floorNumForSep(sep)
          if (floorNum != None)
            return floorNum
      }
    }

    def floorNumForSep(sep: String): Option[Int] = {
      if (aline1.matches(".*\\d" + sep + "\\d.*")) {
        val numStrs = aline1.split(sep)
        val floorNum = numStrs(0).replaceAll("[^\\d]", "")
        if (floorNum.size > 0)
          return Some(Integer.parseInt(floorNum))
      }
      None
    }

    None
  }

  def streetNum(): Int = {
    Integer.parseInt(aline2.replaceAll("[^\\d]", ""))
  }

  val stNumPattern = Pattern.compile("\\d+[a-zA-Z]*")

  //when a street is eg 175B James Street, this will return "B", otherwise None
  def streetNumChar(): Option[String] = {
    val m = stNumPattern.matcher(aline2)
    if (m.lookingAt()) {
      Some(m.group(0).replaceAll("\\d", ""))
    } else None
  }

  def streetName(): String = {
    aline2.replaceAll("\\d+[a-zA-Z]*", "").trim() //sometimes street address can be eg 175B James Street
  }

  override def toString(): String = {
    return aline1 + ":::" + aline2
  }

  def fields: List[String] = {
    var fields: List[String] = Nil
    fields ::= city + " " + postcode
    fields ::= aline2
    if (aline1 != null && aline1 != "")
      fields ::= aline1
    fields ::= firstName + " " + lastName
    fields ::= registerNum
    fields
  }
}